Tables store data. For each column in the table, you
must select a built-in or a user-defined data type. Indexes are created
on tables to maximize query performance. Constraints are associated
with table columns and define the rules to which data in a particular
column or columns must adhere. Constraints can also define
relationships between tables, like the necessity to have a Customer
entity associated with every Order entity. These are known as FOREIGN KEY constraints. In this section we’ll provide you with details about tables, constraints, and indexes.
Working with Tables and Views
Tables
are the database objects that store data in a SQL Server database.
Tables are structured as columns and rows, like a spreadsheet. The
columns define the type and length of data they can store. Every table
must have at least one column. Column names must be unique within a
table; that is, you cannot specify ProductName column to appear twice
in the Product table. Tables store the underlying data within the .mdf
and .ndf data files as pages and extents. Columns are sometimes associated with constraints; for example, PRIMARY KEY, UNIQUE, or DEFAULT. Types of constraints will be explained later in this chapter. You can also mark columns with the following special attributes:
Identity columns
Values for these columns are generated automatically in sequence by
incrementing every time a row is added. Usually, values 1, 2, 3, n are used, but you can define your own seed (starting value) and increment value for the IDENTITY column.
Computed columns These columns do not store any data; instead, they define a formula that calculates the column value at query time.
Timestamp columns These columns are used as a mechanism for version-stamping table rows and tracking changes.
UniqueIdentifier columns
These columns store globally unique identifiers (GUIDs). GUIDs values
are used for replication and are guaranteed to be unique. GUIDs values
can be generated using the NEWID() built-in function.
When defining columns for a new or existing table, you can specify column nullibility.
A column is said to be nullible if it allows storing null (empty)
values. You can choose to mark a column as not nullible. If anyone
attempts to insert a NULL value into this column, an error will be raised, and the INSERT operation will fail. To mark a column as nullible, use the NULL keyword when defining the column in the CREATE TABLE or ALTER TABLE statements. To mark a column as not nullible, use the NOT NULL keyword. By default, columns are nullible. Columns designated as primary keys cannot be nullible.
Creating Tables
Tables can be created and modified using the SQL Server Management Studio table designer or the CREATE TABLE or ALTER TABLE statements. To access the SQL Server
Management Studio graphical table designer, in Object Explorer expand
the database if you wish to create the table. Then, right-click Tables and click New Table. To modify an existing table, right-click it and then click Design.
The table designer shows the columns that will be created for your
table at the top and the properties of the selected column in the Column Properties pane, usually located at the bottom of the screen. Figure 1 shows the use of SQL Server Management Studio to create a new table.
To create a table using DDL, use the CREATE TABLE statement along with the syntax shown in Example 1
Example 1. Create TABLE Statement—Syntax
CREATE TABLE [database_name].[schema_name].table_name (column1_name data_type [NULL | NOT NULL] | [PRIMARY KEY] | [IDENTITY], Column2_name data_type [NULL | NOT NULL], [<computed_column_definition>]
|
In this statement, the table_name is the name of the table you wish to create. When defining columns, you can specify whether or not they will allow NULL values. You can also state that a column will be designated as the PRIMARY KEY for the table and whether it will contain automatically incrementing values, known as IDENTITY columns. The computed_column_definition
is the formula for a calculated column. When defining columns, you must
designate a data type, like varchar or int, and in some cases a length.
Table 1 summarizes built-in data types that are available to you when you are defining columns.
Table 1. Built-In Data Types
Numeric | Character | Dates and Times | Other |
---|
Tinyint | Char | Datetime | Binary |
Smallint | Nchar | Smalldatetime | Bit |
Int | Varchar | Date | Cursor |
Bigint | Nvarchar | Datetime2 | Xml |
Smallmoney | Text | Datetimeoffet | Smalldatetime |
Money | Ntext | Time | Varbinary |
Decimal | | Timestamp | Uniqueidentifier |
Double | | | Hierarchyid |
Float | | | Rowversion |
Real | | | Sql_variant |
| | | Image |
Some
of the data types shown in the table also allow you to specify the
length or precision for the data stored in the column you are creating.
For example, a column of type char(1000) allows you to store up to 1,000 characters per row. A column of type decimal(10) allows you to store up to 10 digits on either side of the decimal point, while decimal(10,5)
allows you to store numbers of up to 10 digits with up to 5 digits to
the right of the decimal point. Variable-length data types, like varchar, nvarchar, and varbinary, consume only the space that the characters stored in the column take up. Fixed-length equivalents of char, nchar, and binary consume a fixed amount of space regardless of the amount of actual data contained in the column. Data types prefixed with “n”—nvarchar and nchar—store Unicode text and can be used to store characters from multiple languages in one column.
Computed Columns
Computed
columns are used when you need to store a calculated value in a table.
As a best practice, you should never physically store a value in a
table that can be derived from other data within the table. If you do
so, you will be consuming disk space unnecessarily. You will also open
yourself up to logic errors, when the base columns have been updated,
but the column storing the derived value is not, and vice versa. SQL
Server offers the computed column feature to overcome these challenges.
Use computed columns when you don’t want to manually calculate a
column’s value in every query and when you wish to simplify your query
syntax.
A
computed column is based on a formula that can reference the values of
noncomputed columns in the same row of the same table. Scalar functions
can also be used in the definition of a computed column. A computed
column cannot reference data in other tables or contain a subquery.
By
default, computed columns are virtual, and the values in them are not
stored on disk. The values are calculated every time the computed
column is queried. When it is more efficient to store the values of
computed columns on disk, you can use the PERSISTED keyword to instruct
SQL Server to physically store the column values. PERSISTED columns are
updated when other columns they are based on are updated, or when new
rows are inserted into the table. Only computed columns using
deterministic functions can be marked as PERSISTED. A function is
deterministic when it is guaranteed to return the same value, if you
pass it the same parameters. For example, the AVG function is
deterministic, while the GETDATE function is not. Whether or not the
computed column is persisted, you can never write directly to it.
Persisted computed columns can be indexed. This is useful if you need
to search and sort by the values of this column.
Creating User-Defined Data Types
Sometimes
you need to create your own data types that are based on the built-in
data types introduced earlier. Custom data types are also known as
user-defined data types. User-defined data types are especially useful
when you must store the data with the same length or precision over and
over again. For example, you can create a new user-defined data type to
represent people’s names. This user-defined data type can be based on nvarchar(50)
and cannot contain nulls. This user-defined data type can now be bound
to any column that is to contain people’s names and will be consistent
throughout. Create your user-defined data types in the Model system
database, so that it is automatically inherited by all new databases
you create. User-defined data types are created using the CREATE TYPE statement. The syntax is shown in Example 2 :
Example 2. Create TYPE Statement—Syntax
CREATE TYPE [schema_name. ]type_name {FROM base_type([precision],[scale]) [NULL | NOT NULL] }
|
Example 3
shows the syntax used to create a user-defined data type named
PersonName and to create a table that contains two columns of type
PersonName.
Example 3. Using the Create TYPE Statement
CREATE TYPE PersonName {FROM varchar(50) NOT NULL }; GO CREATE TABLE TeamMembers (MemberId int PRIMARY KEY, MemberName PersonName, ManagerName PersonName); GO
|
Use the ALTER TYPE statement to change the definition of your user-defined types. The DROP TYPE
statement should be used to remove the user-defined data types you no
longer need in the database. You cannot remove user-defined types from
the database while there are tables with columns based on these types.
If you attempt to use the DROP TYPE
statement to remove a data type that is in use, you will get an error
message similar to: “Msg 3732, Level 16, State 1, Line 1. Cannot drop
type ‘PersonName’ because it is being referenced by object
‘TeamMembers’. There may be other objects that reference this type.”